home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 004 / _spconv / !Spconv / c / ROS-Spconv < prev    next >
Text File  |  1994-09-20  |  35KB  |  1,715 lines

  1. /* Program: ROS-Spconv.c
  2.  *
  3.  * Purpose: ZX-Spectrum 48K snapshot converter
  4.  *          This is a modified source for RISC-OS, suitable for calling from
  5.  *          a wimp front-end.
  6.  *
  7.  * Public Domain software
  8.  *
  9.  * Author: Henk de Groot (c)
  10.  *
  11.  * RISC-OS conversion: Tim Moore (c) 1994
  12.  *
  13.  * Notes:  Based on spconv.c
  14.  * Modified to make suitable for calling by wimp application rather than
  15.  * by command line execution.
  16.  * This version does not have a command line interface. (though the calling
  17.  * program may have).
  18.  * It is up to the caller (ie. wimp program) to determine input and output
  19.  * file types and call the exported routine ('spconv') in the correct
  20.  * manner, rather than this program doing so.
  21.  */
  22.  
  23. /* Standard ANSI includes */
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28.  
  29. /* RISC-OS includes */
  30. #include "os.h"
  31. #include "werr.h"
  32.  
  33. /* The internal header */
  34. #include "ROS-Spconv.h"
  35.  
  36. #ifndef BOOL
  37. #define BOOL int
  38. #define TRUE 1
  39. #define FALSE 0
  40. #endif
  41.  
  42. struct sna_s sna;
  43. struct vga_s vga;
  44. struct z80_s z80;
  45. struct prg_s prg;
  46. struct ach_s ach;
  47. struct kgb_s kgb;
  48.  
  49. /* extra space just in case the Z80 decompress fails due to a corrupt image */
  50. unsigned char image[IMSIZE+0x100]; 
  51. unsigned int z80_size;
  52.  
  53. int    intype;
  54. int    outtype;
  55.  
  56. /* Path names are limited to 80 characters under MSDOS so this sould be */
  57. /* enough... If you are using UNIX than you may have to make this array */
  58. /* larger.                                                              */
  59. char    my_directory[255];
  60.  
  61.  
  62.  
  63. /* Convert 'Infile' (of type 'InFile_Type') to a file of type 'OutFile_Type'
  64.  * (ie. .SNA or .ACH etc)
  65.  * It will place the new file in <Wimp$ScrapDir> and the wimp routines will
  66.  * then let the user save the file to a directory viewer.
  67.  */
  68. int spconv(char *InFile, int InFile_Type, int OutFile_Type)
  69. {
  70.         os_filestr FileStr;
  71.         char            outfile[255];
  72.         long        file_size;
  73.  
  74.         /* Determine the name and location of the output file */
  75.         sprintf(outfile,"%s.NewSnap",getenv("Wimp$ScrapDir"));
  76.  
  77.         /*
  78.          * Find the directory path where this program is started from.
  79.          * This will be needed for finding the spectrum-rom. Some formats
  80.          * need the spectrum-rom for proper conversion.
  81.          */
  82.         sprintf(my_directory,"%s",getenv("SpconvRom$Dir"));
  83.  
  84.         /*
  85.          * Check if the input file exists and fetch the file length of
  86.          * the file in the mean time. Two for the prise of one...
  87.          */
  88.  
  89.         FileStr.action=0x14;
  90.         FileStr.name = (char *) InFile;
  91.         if(os_file(&FileStr) != NULL) {
  92.                 perror(InFile);
  93.                 return EXIT_FILE_ERROR;
  94.         }
  95.         file_size = FileStr.start;
  96.  
  97.  
  98.         /*
  99.          * recognize input type on filename:
  100.          *
  101.          *      .SNA    ->      SNA file (used in JPP)
  102.          *      .SP     ->      SP file (was VGASPEC)
  103.          *      .Z80    ->      Z80 file
  104.          *      .PRG    ->      PRG file
  105.          *      .ACH    ->      ACH file (from archimedes emulator)
  106.          *      .ZX     ->      KGB file (from KGB emulator)
  107.          *      other   ->      if exact 48+header -> raw file
  108.          *      otherwise       unknown
  109.          */
  110.  
  111.         intype = InFile_Type;
  112.  
  113.         if (intype == UNKNOWN) {
  114.                 if (file_size == (hdr_size+IMSIZE)) {
  115.                         intype=RAW;
  116.                 } else {
  117.                         werr(FALSE,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH, .ZX or Raw");
  118.                         return EXIT_FILE_ERROR;
  119.                 }
  120.         }
  121.  
  122.         /*
  123.          * recognize output type on filename:
  124.          *
  125.          *      .SNA    ->      SNA file
  126.          *      .SP     ->      SP file (was VGASPEC)
  127.          *      .Z80    ->      Z80 file
  128.          *      .PRG    ->      PRG file
  129.          *      .ACH    ->      ACH file (from archimedes emulator)
  130.          *      .ZX     ->      KGB file (from KGB emulator)
  131.          *      otherwise       unknown
  132.          */
  133.  
  134.         outtype = OutFile_Type;
  135.  
  136.         if(outtype==UNKNOWN) {
  137.                 werr(FALSE,"Unknown output file format. Must be a .SNA, .SP, .Z80, .PRG, .ACH or .ZX file");
  138.                 return EXIT_FILE_ERROR;
  139.         }
  140.  
  141.  
  142.         /*
  143.          * Special converion between versions of the same type
  144.          */
  145.         if(intype == outtype)
  146.                 return DIRC_direct_convert(intype, InFile, outfile);
  147.  
  148.         /*
  149.          * General conversion from one type to another
  150.          */
  151.  
  152.         /*
  153.          * convert input_file to SNA
  154.          */
  155.  
  156.         switch(intype) {
  157.         case SNA:       if (file_size == (sna_size+IMSIZE)) {
  158.                                 RSNA_read_sna(InFile);
  159.                         }
  160.                         break;
  161.         case SP:        if ((file_size == (vga_size+IMSIZE))) {
  162.                                 RVGA_read_vgaspec(InFile);
  163.                                 VGSN_vgaspec_to_sna();
  164.                         } else if ((file_size == (vga_size+IMSIZE-6))) {
  165.                                 ROVG_read_old_vgaspec(InFile);
  166.                                 VGSN_vgaspec_to_sna();
  167.                         }
  168.                         break;
  169.         case RAW:       RRAW_read_raw(InFile);
  170.                         RASN_raw_to_sna();
  171.                         break;
  172.         case Z80:       RZ80_read_z80(InFile);
  173.                         Z8SN_z80_to_sna();
  174.                         break;
  175.         case PRG:       if(file_size != (prg_size+IMSIZE)) {
  176.                                 werr(FALSE,"Warning: the image part of input is not 48k!  Converting anyway, the converted file may not work");
  177.                         }
  178.                         RPRG_read_prg(InFile);
  179.                         PRSN_prg_to_sna();
  180.                         break;
  181.         case ACH:       if(file_size == (ach_size+16384L+IMSIZE)) {
  182.                                 RACH_read_ach(InFile);
  183.                                 ACSN_ach_to_sna();
  184.                         }
  185.                         break;
  186.         case KGB:       if(file_size == (132L+IMSIZE+kgb_size)) {
  187.                                 RKGB_read_kgb(InFile);
  188.                                 KGSN_kgb_to_sna();
  189.                         }
  190.                         break;
  191.         default:        werr(FALSE,"Unrecognized input file type, can't convert");
  192.                         return EXIT_FILE_ERROR;
  193.         }
  194.  
  195.         /*
  196.          * convert internal SNA format to output file
  197.          */
  198.  
  199.         switch(outtype) {
  200.         case SNA:       WSNA_write_sna(outfile);
  201.                         break;
  202.         case SP:        SNVG_sna_to_vgaspec();
  203.                         WVGA_write_vgaspec(outfile);
  204.                         break;
  205.         case Z80:       SNZ8_sna_to_z80();
  206.                         WZ80_write_z80(outfile);
  207.                         break;
  208.         case PRG:       SNPR_sna_to_prg(outfile);
  209.                         WPRG_write_prg(outfile);
  210.                         break;
  211.         case ACH:       SNAC_sna_to_ach();
  212.                         WACH_write_ach(outfile);
  213.                         break;
  214.         case KGB:       SNKG_sna_to_kgb();
  215.                         WKGB_write_kgb(outfile);
  216.                         break;
  217.         default:        werr(FALSE,"Unrecognized output file type, can't convert");
  218.                         return EXIT_FILE_ERROR;
  219.         }
  220.  
  221.         /*
  222.          * That's it, simple isn't it?
  223.          */
  224.         return EXIT_OK;
  225. }
  226.  
  227. /* SPECIAL FUNCTIONS */
  228.  
  229.  
  230. /* Special converion between versions of the same type */
  231.  
  232. int DIRC_direct_convert(int type, char * infile, char * outfile)
  233. {
  234.     os_filestr FileStr;
  235.     long        file_size;
  236.  
  237.     /*
  238.      * Special conversion between versions of the same type.
  239.      * These conversion don't use the intermediate 'sna' format
  240.      * to preserve as much information as possible.
  241.      *
  242.      * This currently only applies to .SP and the .Z80 formats.
  243.      *
  244.      * The .SP formats will convert from the New to the Old format or
  245.      * from the Old to the New format, controled by the current format
  246.      * of the input.
  247.      *
  248.      * The .Z80 formats will convert to the version 1.45 .Z80 format
  249.      * since version 1.45 .Z80 files can be read by both old and new
  250.      * Z80-emulators.
  251.      */
  252.  
  253.     /* check if it is for the SP format */
  254.     if(type == SP) {
  255.             FileStr.action=0x14;
  256.             FileStr.name = (char *) infile;
  257.             if (os_file(&FileStr) != NULL) {
  258.             perror(infile);
  259.             return EXIT_FILE_ERROR;
  260.         }
  261.         file_size = FileStr.start;
  262.  
  263.         if((file_size == (vga_size+IMSIZE))) {
  264.             /* printf("Converting %s from new .SP format to old .SP format.",infile); */
  265.             RVGA_read_vgaspec(infile);
  266.  
  267.             WOVG_write_old_vgaspec(outfile);
  268.             return EXIT_OK;
  269.         }
  270.  
  271.         if((file_size == (vga_size+IMSIZE-6))) {
  272.             RVGH_read_vgaspec_header(infile);
  273.  
  274.             if((vga.S=='S')&&(vga.P=='P')) {
  275. werr(FALSE,"Invalid input file format. This could be a new syle .SP file with an image of another length than 48Kb.");
  276. werr(FALSE,"This kind of .SP files cannot be converted. All other file formats (including the old .SP format) contain images of 48Kb length.");
  277.                 return EXIT_FILE_ERROR;
  278.             }
  279.  
  280.             /* printf("Converting %s from old .SP format to new .SP format.\n",infile); */
  281.             ROVG_read_old_vgaspec(infile);
  282.  
  283.             /* These values are fixed for a full 48K .SP file */
  284.             vga.S='S';
  285.             vga.P='P';
  286.             vga.len_l=0x00;
  287.             vga.len_h=0xC0;
  288.             vga.start_l=0x00;
  289.             vga.start_h=0x40;
  290.  
  291.             WVGA_write_vgaspec(outfile);
  292.  
  293.             return EXIT_OK;
  294.         } else {
  295.             RVGH_read_vgaspec_header(infile);
  296.             if((vga.S=='S')&&(vga.P=='P')) {
  297. werr(FALSE,"Invalid input file format. This could be a new syle .SP file with an image of another length than 48Kb.");
  298. werr(FALSE,"This kind of .SP files cannot be converted. All other file formats (including the old .SP format) contain images of 48Kb length.");
  299.             } else {
  300. werr(FALSE,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH, .ZX or Raw");
  301.             }
  302.             return EXIT_FILE_ERROR;
  303.         }
  304.     }
  305.  
  306.     if(type == Z80)
  307.     {
  308.         /* printf("Converting %s from .Z80 to .Z80 (output in version 1.45 format)\n",infile);   */
  309.         RZ80_read_z80(infile);
  310.  
  311.         WZ80_write_z80(outfile);
  312.         return EXIT_OK;
  313.     }
  314.  
  315.     /* If we get here than we had no special handling for this type */
  316.     /* return an error in that case...                              */
  317.     werr(FALSE,"Input and output file format are the same. Try copying instead!");
  318.  
  319.     return EXIT_USAGE;
  320. }
  321.  
  322. /* ERROR HANDLING FUNCTIONS */
  323.  
  324. void RERR_read_error(char * s, FILE * fd)
  325. {
  326.     perror(s);
  327.     if(fd != NULL) fclose(fd);
  328.     exit(EXIT_READ_ERROR);
  329. }
  330.  
  331. void WERR_write_error(char * s, FILE * fd)
  332. {
  333.     perror(s);
  334.     if(fd != NULL) fclose(fd);
  335.     exit(EXIT_WRITE_ERROR);
  336. }
  337.  
  338. /* I/O FUNCTIONS */
  339.  
  340. /* GENERIC I/O - READ/WRITE SNAPSHOT */
  341.  
  342. void RGEN_read_generic(char * s, void * header, size_t h_size)
  343. {
  344.     FILE * fd;
  345.  
  346.     fd=fopen(s,"r");
  347.     if(fd == NULL)
  348.         RERR_read_error(s, fd);
  349.  
  350.     if(fread(header, h_size, 1, fd)!=1)
  351.         RERR_read_error(s, fd);
  352.  
  353.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  354.         RERR_read_error(s, fd);
  355.  
  356.     fclose(fd);
  357. }
  358.  
  359. void WGEN_write_generic(char * s, void * header, size_t h_size)
  360. {
  361.     FILE * fd;
  362.  
  363.     remove(s);
  364.  
  365.     fd=fopen(s,"w");
  366.     if(fd == NULL)
  367.         WERR_write_error(s, fd);
  368.  
  369.     if(fwrite(header, h_size, 1, fd)!=1)
  370.         WERR_write_error(s, fd);
  371.  
  372.     if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
  373.         WERR_write_error(s, fd);
  374.  
  375.     fclose(fd);
  376. }
  377.  
  378. /* SPECIFIC I/O - READ/WRITE .SNA IMAGE */
  379.  
  380. void RSNA_read_sna(char * s)
  381. {
  382.     RGEN_read_generic(s, (void *) &sna, sna_size);
  383. }
  384.  
  385. void WSNA_write_sna(char * s)
  386. {
  387.     WGEN_write_generic(s, (void *) &sna, sna_size);
  388. }
  389.  
  390. /* SPECIFIC I/O - READ NEW .SP HEADER */
  391.  
  392. void RVGH_read_vgaspec_header(char * s)
  393. {
  394.     FILE * fd;
  395.  
  396.     fd=fopen(s,"r");
  397.     if(fd == NULL)
  398.         RERR_read_error(s, fd);
  399.  
  400.     if(fread(&vga,vga_size,1,fd)!=1)
  401.         RERR_read_error(s, fd);
  402.  
  403.     fclose(fd);
  404. }
  405.  
  406. /* SPECIFIC I/O - READ/WRITE NEW .SP IMAGE */
  407.  
  408. void RVGA_read_vgaspec(char * s)
  409. {
  410.     RGEN_read_generic(s, (void *) &vga, vga_size);
  411. }
  412.  
  413. void WVGA_write_vgaspec(char * s)
  414. {
  415.     WGEN_write_generic(s, (void *) &vga, vga_size);
  416. }
  417.  
  418. /* SPECIFIC I/O - READ/WRITE OLD .SP IMAGE */
  419.  
  420. void ROVG_read_old_vgaspec(char * s)
  421. {
  422.     RGEN_read_generic(s, (void *)(((char *)&vga)+6), (unsigned int) (vga_size-6));
  423. }
  424.  
  425. void WOVG_write_old_vgaspec(char * s)
  426. {
  427.     WGEN_write_generic(s, (void *)(((char *)&vga)+6), (unsigned int) (vga_size-6));
  428. }
  429.  
  430. /* SPECIFIC I/O - READ RAW IMAGE */
  431.  
  432. void RRAW_read_raw(char * s)
  433. {
  434.     int i;
  435.     FILE * fd;
  436.  
  437.     fd=fopen(s,"r");
  438.     if(fd == NULL)
  439.         RERR_read_error(s, fd);
  440.  
  441.     if(fread(&h, hdr_size, 1, fd)!=1)
  442.         RERR_read_error(s, fd);
  443.  
  444.     /* check if the image was saved the correct way */
  445.     for(i=0;i<9;i++) {
  446.         if(h.in[i]!=expect[i]) {
  447.             werr(FALSE,"Header of spectum image not ok, Spectrum image should be saved with: SAVE *\"b\"CODE 16384,49152");
  448.             fclose(fd);
  449.             exit(EXIT_FILE_ERROR);
  450.         }
  451.     }
  452.  
  453.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  454.         RERR_read_error(s, fd);
  455.  
  456.     fclose(fd);
  457. }
  458.  
  459. /* SPECIFIC I/O - READ/WRITE .Z80 IMAGE */
  460.  
  461. void RZ80_read_z80(char * s)
  462. {
  463.     FILE * fd;
  464.  
  465.     fd=fopen(s,"r");
  466.     if(fd == NULL)
  467.         RERR_read_error(s, fd);
  468.  
  469.     /* read old header part */
  470.     if(fread(&z80,z80_145_size,1,fd)!=1)
  471.         RERR_read_error(s, fd);
  472.  
  473.     /* check for 2.01 format */
  474.     if((z80.pch == (unsigned char) 0) &&
  475.        (z80.pcl == (unsigned char) 0)) {
  476.  
  477.         /* 2.01 or better format, check if we can use this */
  478.         unsigned char *p;
  479.         p = (unsigned char *) &z80;
  480.  
  481.         /* read an aditional 2 bytes */
  482.         if(fread(&p[z80_145_size],2,1,fd)!=1)
  483.             RERR_read_error(s, fd);
  484.  
  485.         if((p[z80_145_size] != (unsigned char) 23) &&
  486.            (p[z80_145_size+1] != (unsigned char) 0)) {
  487.             werr(FALSE,"%s seems to be a new type Z80 file! This program can only read files up to version 2.01 format",s);
  488.             fclose(fd);
  489.             exit(EXIT_FILE_ERROR);
  490.         }
  491.  
  492.         /* we passed this test, read the 23 byte long extra header */
  493.         if(fread(&p[z80_145_size+2],23,1,fd)!=1)
  494.             RERR_read_error(s, fd);
  495.  
  496.         /* we got a complete header now. */
  497.         /* check the type of the file... */
  498.         if((unsigned int) z80.hardware >= 3) {
  499.             werr(FALSE,"%s is not a 48K Spectrum Z80 file, can't convert!",s);
  500.             fclose(fd);
  501.             exit(EXIT_FILE_ERROR);
  502.         }
  503.         /* check if the interface-1 rom was paged in */
  504.         if(z80.if1_paged != (unsigned char) 0) {
  505.             werr(FALSE,"%s has interface-1 rom paged in, can't convert!",s);
  506.             fclose(fd);
  507.             exit(EXIT_FILE_ERROR);
  508.         }
  509.         /* all fine up till now, put PC back to the old place and reset the */
  510.         /* compressed memory bit, the z80_read_page function decompresses.  */
  511.         z80.pch = z80.n_pch;
  512.         z80.pcl = z80.n_pcl;
  513.         z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  514.  
  515.         while(RDPG_z80_read_page(s, fd)!=0);
  516.     } else {
  517.         /* The file is in version 1.45 format.             */
  518.         /* Read and decompress if the image is compressed, */
  519.         /* just read if it is not compressed at all...     */
  520.  
  521.         if((z80.data & 0x20)!=0) {
  522.             Z80D_z80_decompress(fd,0,(unsigned int) IMSIZE);
  523.             z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  524.         } else {
  525.             if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  526.                 RERR_read_error(s, fd);
  527.         }
  528.     }
  529.     fclose(fd);
  530. }
  531.  
  532. void WZ80_write_z80(char * s)
  533. {
  534.     FILE * fd;
  535.  
  536.     /* Try to compress the data */
  537.     z80.data=z80.data | Z80C_z80_compress();
  538.  
  539.     remove(s);
  540.  
  541.     fd=fopen(s,"w");
  542.     if(fd == NULL)
  543.         WERR_write_error(s, fd);
  544.  
  545.     if(fwrite(&z80, z80_145_size, 1, fd)!=1)
  546.         WERR_write_error(s, fd);
  547.  
  548.     if(fwrite(image, (size_t) z80_size, 1, fd)!=1)
  549.         WERR_write_error(s, fd);
  550.  
  551.     fclose(fd);
  552. }
  553.  
  554. /* SPECIFIC I/O - READ/WRITE .PRG IMAGE */
  555.  
  556. void RPRG_read_prg(char * s)
  557. {
  558.     RGEN_read_generic(s, (void *) &prg, prg_size);
  559. }
  560.  
  561. void WPRG_write_prg(char * s)
  562. {
  563.     WGEN_write_generic(s, (void *) &prg, prg_size);
  564. }
  565.  
  566. /* SPECIFIC I/O - READ/WRITE .ACH IMAGE */
  567.  
  568. void RACH_read_ach(char * s)
  569. {
  570.     FILE * fd;
  571.  
  572.     fd=fopen(s,"r");
  573.     if(fd == NULL)
  574.         RERR_read_error(s, fd);
  575.  
  576.     if(fread(&ach,ach_size,1,fd)!=1)
  577.         RERR_read_error(s, fd);
  578.  
  579.     /* fseek over the 16K ram area */
  580.     if(fseek(fd,16384L,SEEK_CUR)!=0)
  581.         RERR_read_error(s, fd);
  582.  
  583.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  584.         RERR_read_error(s, fd);
  585.  
  586.     fclose(fd);
  587. }
  588.  
  589. void WACH_write_ach(char * s)
  590. {
  591.     char buffer[1024];
  592.     char *p;
  593.     int  i;
  594.     os_filestr FileStr;
  595.     const char * rom;
  596.     FILE * fd;
  597.     long file_size;
  598.  
  599.     /* clean buffer first */
  600.     p=(char *) buffer;
  601.     for(i=0; i < 1024; i++) p[i]='\0';
  602.  
  603.     remove(s);
  604.  
  605.     fd=fopen(s,"w");
  606.     if(fd == NULL)
  607.         WERR_write_error(s, fd);
  608.  
  609.     if(fwrite(&ach,ach_size,1,fd)!=1)
  610.         WERR_write_error(s, fd);
  611.  
  612.     strcat(my_directory,".RomImage");
  613.  
  614.     rom=NULL;
  615.  
  616.         FileStr.action=0x14;
  617.         FileStr.name = (char *) my_directory;
  618.         if (os_file(&FileStr) == NULL) {
  619.                 rom=(const char *) my_directory;
  620.         }
  621.         
  622.         printf("-d1- rom=%s\n",rom);
  623.     file_size = FileStr.start;
  624.         printf("-d2- file_size=%ld\n",file_size);
  625.  
  626.     if(rom==NULL) {
  627.         werr(FALSE,"Warning: Can't find \"RomImage\" Converting anyway.");
  628.  
  629.         /* write the 16K ram area as zero's */
  630.         for(i=0; i < 16; i++) {
  631.             if(fwrite(buffer,1024,1,fd)!=1)
  632.                 WERR_write_error(s, fd);
  633.         }
  634.     } else {
  635.         if (file_size != 16384) {
  636.         werr(FALSE,"Warning:\"RomImage\" is the wrong size (not 16k) Converting anyway.");
  637.  
  638.             /* copy the 16K ROM area */
  639.             for(i=0; i < 16; i++) {
  640.                 if(fwrite(buffer,1024,1,fd)!=1)
  641.                     WERR_write_error(s, fd);
  642.             }
  643.         } else {
  644.             FILE * fd_specrom;
  645.  
  646.             /* printf("Using Spectrum ROM: %s\n",rom); */
  647.  
  648.             fd_specrom=fopen(rom,"r");
  649.             if(fd_specrom==NULL) {
  650.                 perror(rom);
  651.                 fclose(fd);
  652.                 exit(EXIT_WRITE_ERROR);
  653.             }
  654.  
  655.             for(i=0; i < 16; i++) {
  656.                 if(fread(buffer,1024,1,fd_specrom)!=1) {
  657.                     perror(rom);
  658.                     fclose(fd_specrom);
  659.                     fclose(fd);
  660.                     exit(EXIT_WRITE_ERROR);
  661.                 }
  662.                 if(fwrite(buffer,1024,1,fd)!=1) {
  663.                     perror(s);
  664.                     fclose(fd_specrom);
  665.                     fclose(fd);
  666.                     exit(EXIT_WRITE_ERROR);
  667.                 }
  668.             }
  669.             fclose(fd_specrom);
  670.         }
  671.     }
  672.  
  673.     if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
  674.         WERR_write_error(s, fd);
  675.  
  676.     fclose(fd);
  677. }
  678.  
  679. /* SPECIFIC I/O - READ/WRITE .ZX IMAGE */
  680.  
  681. void RKGB_read_kgb(char * s)
  682. {
  683.     FILE * fd;
  684.  
  685.     fd=fopen(s,"r");
  686.     if(fd == NULL)
  687.         RERR_read_error(s, fd);
  688.  
  689.     /* fseek over the first 132 bytes */
  690.     if(fseek(fd,132L,SEEK_CUR)!=0)
  691.         RERR_read_error(s, fd);
  692.  
  693.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  694.         RERR_read_error(s, fd);
  695.  
  696.     if(fread(&kgb,kgb_size,1,fd)!=1)
  697.         RERR_read_error(s,fd);
  698.  
  699.     fclose(fd);
  700. }
  701.  
  702. void WKGB_write_kgb(char * s)
  703. {
  704.     char buffer[132];
  705.     char *p;
  706.     int  i;
  707.     os_filestr FileStr;
  708.     const char * rom;
  709.     FILE * fd;
  710.     long file_size;
  711.  
  712.     /* clean buffer first */
  713.     p=(char *) buffer;
  714.     for(i=0; i < 132; i++) p[i]='\0';
  715.  
  716.     remove(s);
  717.  
  718.     fd=fopen(s,"w");
  719.     if(fd == NULL)
  720.         WERR_write_error(s, fd);
  721.  
  722.     strcat(my_directory,".RomImage");
  723.  
  724.     rom=NULL;
  725.  
  726.         FileStr.action=0x14;
  727.         FileStr.name = (char *) my_directory;
  728.         if (os_file(&FileStr) == NULL) {
  729.                 rom=(const char *) my_directory;
  730.         }
  731.         
  732.         printf("-d1- rom=%s\n",rom);
  733.     file_size = FileStr.start;
  734.         printf("-d2- file_size=%ld\n",file_size);
  735.  
  736.     if(rom==NULL) {
  737.         werr(FALSE,"Warning: Can't find \"RomImage\" Converting anyway.");
  738.  
  739.         /* write the 132 byte area as zero's */
  740.         if(fwrite(buffer,132,1,fd)!=1)
  741.             WERR_write_error(s, fd);
  742.     } else {
  743.         if (file_size != 16384) {
  744.         werr(FALSE,"Warning: \"RomImage\" is the wrong size (not 16k) Converting anyway.");
  745.  
  746.             /* write the 132 byte area as zero's */
  747.             if(fwrite(buffer,132,1,fd)!=1)
  748.                 WERR_write_error(s, fd);
  749.         } else {
  750.             FILE * fd_specrom;
  751.  
  752.             /* printf("Using Spectrum ROM: %s\n",rom); */
  753.  
  754.             fd_specrom=fopen(rom,"r");
  755.  
  756.             if(fd_specrom == NULL) {
  757.                 perror(rom);
  758.                 fclose(fd);
  759.                 exit(EXIT_WRITE_ERROR);
  760.             }
  761.  
  762.             /* fseek over the first 16384-132 bytes */
  763.             if(fseek(fd_specrom,16252L,SEEK_CUR)!=0) {
  764.                 perror(rom);
  765.                 fclose(fd_specrom);
  766.                 fclose(fd);
  767.                 exit(EXIT_WRITE_ERROR);
  768.             }
  769.             if(fread(buffer,132,1,fd_specrom)!=1) {
  770.                 perror(rom);
  771.                 fclose(fd_specrom);
  772.                 fclose(fd);
  773.                 exit(EXIT_WRITE_ERROR);
  774.             }
  775.             if(fwrite(buffer,132,1,fd)!=1) {
  776.                 perror(s);
  777.                 fclose(fd_specrom);
  778.                 fclose(fd);
  779.                 exit(EXIT_WRITE_ERROR);
  780.             }
  781.             fclose(fd_specrom);
  782.         }
  783.     }
  784.  
  785.     if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
  786.         WERR_write_error(s, fd);
  787.  
  788.     if(fwrite(&kgb,kgb_size,1,fd)!=1)
  789.         WERR_write_error(s, fd);
  790.  
  791.     fclose(fd);
  792. }
  793.  
  794. /* CONVERSION FUNCTIONS - TO .SNA FORMAT */
  795.  
  796. void VGSN_vgaspec_to_sna()
  797. {
  798.     unsigned int addr;
  799.     unsigned int sp;
  800.  
  801.     sna.f=vga.f;
  802.     sna.a=vga.a;
  803.     sna.b=vga.b;
  804.     sna.c=vga.c;
  805.     sna.d=vga.d;
  806.     sna.e=vga.e;
  807.     sna.h=vga.h;
  808.     sna.l=vga.l;
  809.  
  810.     sna.fax=vga.fax;
  811.     sna.aax=vga.aax;
  812.     sna.bax=vga.bax;
  813.     sna.cax=vga.cax;
  814.     sna.dax=vga.dax;
  815.     sna.eax=vga.eax;
  816.     sna.hax=vga.hax;
  817.     sna.lax=vga.lax;
  818.  
  819.     sna.ixh=vga.ixh;
  820.     sna.ixl=vga.ixl;
  821.     sna.iyh=vga.iyh;
  822.     sna.iyl=vga.iyl;
  823.  
  824.     sna.border=vga.border; 
  825.  
  826.     sna.i=vga.i;
  827.     sna.r=vga.r;
  828.  
  829.     /* If register I has changed, chances are good that it runs in
  830.        IM2 mode */
  831.     if(sna.i==0x3f)
  832.         sna.im=0x01; 
  833.     else
  834.         sna.im=0x02; 
  835.         
  836.     if((vga.im & 0x01) == 0)
  837.         sna.iff2=0x00;
  838.     else
  839.         sna.iff2=0xff;
  840.  
  841.     sp=256*vga.sph+vga.spl;
  842.     sp=sp-2;
  843.     addr=sp-0x4000;
  844.     image[addr]=vga.pcl;
  845.     image[addr+1]=vga.pch;
  846.         
  847.     sna.sph=sp/256;
  848.     sna.spl=sp%256;
  849. }
  850.  
  851. void RASN_raw_to_sna()
  852. {
  853.     unsigned int addr;
  854.     unsigned int sp;
  855.     unsigned int pc;
  856.  
  857.     pc=0x1bf4; /* entry of "next statement" */
  858.  
  859.     sna.f=0x99;
  860.     sna.a=0x5f;
  861.     sna.b=0x1f;
  862.     sna.c=0xf0;
  863.     sna.d=0x5d;
  864.     sna.e=0x0c;
  865.     sna.h=0x5d;
  866.     sna.l=0x0e;
  867.  
  868.     sna.fax=0x44;
  869.     sna.aax=0x00;
  870.     sna.bax=0x18;
  871.     sna.cax=0x20;
  872.     sna.dax=0x00;
  873.     sna.eax=0x07;
  874.     sna.hax=0x5c;
  875.     sna.lax=0xf1;
  876.  
  877.     sna.ixh=0x03;
  878.     sna.ixl=0xd4;
  879.     sna.iyh=0x5c;
  880.     sna.iyl=0x3a;
  881.  
  882.     sna.i=0x3f;
  883.     sna.r=0x00;
  884.     sna.im=0x01;
  885.     sna.iff2=0xFF;
  886.  
  887.     /* set sp by means of RAMTOP in the image */
  888.     addr=0x5cb2-0x4000;
  889.     sp=256*image[addr+1]+image[addr]-1;
  890.  
  891.     /* Reset ERR NR to no error */
  892.     image[0x5c3a-0x4000]=0xff;
  893.     
  894.     /* Set border by means of BORDCR */
  895.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  896.     
  897.     /* put return address to MAIN-4 (0x1303) on stack */
  898.     sp=sp-2;
  899.     addr=sp-0x4000;    
  900.     image[addr]=0x03; 
  901.     image[addr+1]=0x13;
  902.     
  903.     sp=sp-2;
  904.     addr=sp-0x4000;
  905.     image[addr]=pc%256;
  906.     image[addr+1]=pc/256;
  907.  
  908.     sna.sph=sp/256;
  909.     sna.spl=sp%256;
  910. }
  911.  
  912. void Z8SN_z80_to_sna()
  913. {
  914.     unsigned int addr;
  915.     unsigned int sp;
  916.  
  917.     sna.f=z80.f;
  918.     sna.a=z80.a;
  919.     sna.b=z80.b;
  920.     sna.c=z80.c;
  921.     sna.d=z80.d;
  922.     sna.e=z80.e;
  923.     sna.h=z80.h;
  924.     sna.l=z80.l;
  925.  
  926.     sna.fax=z80.fax;
  927.     sna.aax=z80.aax;
  928.     sna.bax=z80.bax;
  929.     sna.cax=z80.cax;
  930.     sna.dax=z80.dax;
  931.     sna.eax=z80.eax;
  932.     sna.hax=z80.hax;
  933.     sna.lax=z80.lax;
  934.  
  935.     sna.ixh=z80.ixh;
  936.     sna.ixl=z80.ixl;
  937.     sna.iyh=z80.iyh;
  938.     sna.iyl=z80.iyl;
  939.  
  940.     sna.border=(z80.data/2) & 0x07; 
  941.  
  942.     sna.i=z80.i;
  943.  
  944.     if(z80.data==0xff) z80.data=0;
  945.  
  946.     if((z80.data & 0x01)==1)
  947.         sna.r=(z80.r & 0x7f)+0x80;
  948.     else
  949.         sna.r=z80.r & 0x7f;
  950.  
  951.     sna.im=z80.im & 0x03;
  952.     
  953.     if(z80.iff2 != 0)
  954.         sna.iff2=0xff;
  955.     else
  956.         sna.iff2=0x00;
  957.  
  958.     sp=256*z80.sph+z80.spl;
  959.     sp=sp-2;
  960.     addr=sp-0x4000;
  961.         
  962.     sna.sph=sp/256;
  963.     sna.spl=sp%256;
  964.  
  965.     image[addr]=z80.pcl;
  966.     image[addr+1]=z80.pch;
  967. }
  968.  
  969. void PRSN_prg_to_sna()
  970. {
  971.     unsigned int addr;
  972.     unsigned int sp;
  973.  
  974.     sna.b=prg.b;
  975.     sna.c=prg.c;
  976.     sna.d=prg.d;
  977.     sna.e=prg.e;
  978.     sna.h=prg.h;
  979.     sna.l=prg.l;
  980.     sna.fax=prg.fax;
  981.     sna.aax=prg.aax;
  982.     sna.bax=prg.bax;
  983.     sna.cax=prg.cax;
  984.     sna.dax=prg.dax;
  985.     sna.eax=prg.eax;
  986.     sna.hax=prg.hax;
  987.     sna.lax=prg.lax;
  988.  
  989.     sna.ixh=prg.ixh;
  990.     sna.ixl=prg.ixl;
  991.     sna.iyh=prg.iyh;
  992.     sna.iyl=prg.iyl;
  993.  
  994.     /* Set border by means of BORDCR */
  995.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  996.  
  997.     sna.i=prg.i;
  998.  
  999.     if(prg.i==0x3f)
  1000.         sna.im=0x01;
  1001.     else
  1002.         sna.im=0x02;
  1003.  
  1004.     sp=256*prg.sph+prg.spl;
  1005.     sp=sp+4; /* there are two more words on the stack besides PC */
  1006.     addr=sp-0x4000;
  1007.  
  1008.     sna.r=image[addr-3];
  1009.     /* the af combo is on the stack */
  1010.     sna.f=image[addr-2];
  1011.     sna.a=image[addr-1];
  1012.         
  1013.     sna.sph=sp/256;
  1014.     sna.spl=sp%256;
  1015.  
  1016.     /* interrupts always on ??? */
  1017.     sna.iff2=prg.iff2;
  1018. }
  1019.  
  1020. void ACSN_ach_to_sna()
  1021. {
  1022.     unsigned int addr;
  1023.     unsigned int sp;
  1024.  
  1025.     sna.f=ach.f;
  1026.     sna.a=ach.a;
  1027.     sna.b=ach.b;
  1028.     sna.c=ach.c;
  1029.     sna.d=ach.d;
  1030.     sna.e=ach.e;
  1031.     sna.h=ach.h;
  1032.     sna.l=ach.l;
  1033.  
  1034.     sna.fax=ach.fax;
  1035.     sna.aax=ach.aax;
  1036.     sna.bax=ach.bax;
  1037.     sna.cax=ach.cax;
  1038.     sna.dax=ach.dax;
  1039.     sna.eax=ach.eax;
  1040.     sna.hax=ach.hax;
  1041.     sna.lax=ach.lax;
  1042.  
  1043.     sna.ixh=ach.ixh;
  1044.     sna.ixl=ach.ixl;
  1045.     sna.iyh=ach.iyh;
  1046.     sna.iyl=ach.iyl;
  1047.  
  1048.     sna.border=ach.border;
  1049.  
  1050.     sna.i=ach.i;
  1051.  
  1052.     sna.r=ach.r;
  1053.  
  1054.     sna.im=ach.im & 0x03; 
  1055.     if(sna.im == 3)
  1056.          sna.im = 0;
  1057.         
  1058.     sna.iff2=ach.iff2;
  1059.  
  1060.     sp=256*ach.sph+ach.spl;
  1061.     sp=sp-2;
  1062.     addr=sp-0x4000;
  1063.         
  1064.     sna.sph=sp/256;
  1065.     sna.spl=sp%256;
  1066.  
  1067.     image[addr]=ach.pcl;
  1068.     image[addr+1]=ach.pch;
  1069. }
  1070.  
  1071. void KGSN_kgb_to_sna()
  1072. {
  1073.     unsigned int addr;
  1074.     unsigned int sp;
  1075.  
  1076.     sna.f=kgb.f;
  1077.     sna.a=kgb.a;
  1078.     sna.b=kgb.b;
  1079.     sna.c=kgb.c;
  1080.     sna.d=kgb.d;
  1081.     sna.e=kgb.e;
  1082.     sna.h=kgb.h;
  1083.     sna.l=kgb.l;
  1084.  
  1085.     sna.fax=kgb.fax;
  1086.     sna.aax=kgb.aax;
  1087.     sna.bax=kgb.bax;
  1088.     sna.cax=kgb.cax;
  1089.     sna.dax=kgb.dax;
  1090.     sna.eax=kgb.eax;
  1091.     sna.hax=kgb.hax;
  1092.     sna.lax=kgb.lax;
  1093.  
  1094.     sna.ixh=kgb.ixh;
  1095.     sna.ixl=kgb.ixl;
  1096.     sna.iyh=kgb.iyh;
  1097.     sna.iyl=kgb.iyl;
  1098.  
  1099.     sna.i=kgb.i;
  1100.     sna.r=kgb.r;
  1101.  
  1102.     /* border-colour not found in KGB image */
  1103.     /* Set border by means of BORDCR */
  1104.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1105.  
  1106.     /* determine interrupt mode using the value of register I */
  1107.     if (kgb.i_mode_l==0xff)
  1108.         sna.im=0x00;
  1109.     else if(kgb.i_mode_l==1)
  1110.         sna.im=0x02; 
  1111.     else
  1112.         sna.im=0x01;
  1113.         
  1114.     if((kgb.interruptstatus & 0x01) != 0)
  1115.         sna.iff2=0xff;
  1116.     else
  1117.         sna.iff2=0x0;
  1118.  
  1119.     sp=256*kgb.sph+kgb.spl;
  1120.     sp=sp-2;
  1121.     addr=sp-0x4000;
  1122.         
  1123.     sna.sph=sp/256;
  1124.     sna.spl=sp%256;
  1125.  
  1126.     image[addr]=kgb.pcl;
  1127.     image[addr+1]=kgb.pch;
  1128. }
  1129.  
  1130. /* CONVERSION FUNCTIONS - FROM .SNA FORMAT */
  1131.  
  1132. void SNVG_sna_to_vgaspec()
  1133. {
  1134.     unsigned int addr;
  1135.     unsigned int sp;
  1136.     unsigned int pc;
  1137.  
  1138.     sp=256*sna.sph+sna.spl;
  1139.     addr=sp-0x4000;
  1140.     pc=image[addr]+256*image[addr+1];
  1141.     sp=sp+2;
  1142.  
  1143.     vga.S='S';
  1144.     vga.P='P';
  1145.     vga.len_l=0x00;
  1146.     vga.len_h=0xC0;
  1147.     vga.start_l=0x00;
  1148.     vga.start_h=0x40;
  1149.     vga.f=sna.f;
  1150.     vga.a=sna.a;
  1151.     vga.b=sna.b;
  1152.     vga.c=sna.c;
  1153.     vga.d=sna.d;
  1154.     vga.e=sna.e;
  1155.     vga.h=sna.h;
  1156.     vga.l=sna.l;
  1157.  
  1158.     vga.fax=sna.fax;
  1159.     vga.aax=sna.aax;
  1160.     vga.bax=sna.bax;
  1161.     vga.cax=sna.cax;
  1162.     vga.dax=sna.dax;
  1163.     vga.eax=sna.eax;
  1164.     vga.hax=sna.hax;
  1165.     vga.lax=sna.lax;
  1166.  
  1167.     vga.ixh=sna.ixh;
  1168.     vga.ixl=sna.ixl;
  1169.     vga.iyh=sna.iyh;
  1170.     vga.iyl=sna.iyl;
  1171.  
  1172.     vga.i=sna.i;
  1173.     vga.r=sna.r;
  1174.  
  1175.     vga.im=sna.im & 0x02; /* 0 for IM1, 2 for IM2 */
  1176.  
  1177.     /* works? how does it know it was IM1 ? */
  1178.     if((sna.iff2 & 0x04) != 0)
  1179.         vga.im=vga.im | 0x01; 
  1180.  
  1181.     vga.sph=sp/256;
  1182.     vga.spl=sp%256;
  1183.     
  1184.     vga.pch=pc/256;
  1185.     vga.pcl=pc%256;
  1186.  
  1187.     vga.border=sna.border; 
  1188.  
  1189.     vga.res2=0;
  1190.     vga.res3=0;
  1191.     vga.res4=0;
  1192.     vga.res5=0;
  1193. }
  1194.  
  1195. void SNZ8_sna_to_z80()
  1196. {
  1197.     unsigned int addr;
  1198.     unsigned int sp;
  1199.     unsigned int pc;
  1200.  
  1201.     sp=256*sna.sph+sna.spl;
  1202.     addr=sp-0x4000;
  1203.     pc=image[addr]+256*image[addr+1];
  1204.     sp=sp+2;
  1205.  
  1206.     z80.f=sna.f;
  1207.     z80.a=sna.a;
  1208.     z80.b=sna.b;
  1209.     z80.c=sna.c;
  1210.     z80.d=sna.d;
  1211.     z80.e=sna.e;
  1212.     z80.h=sna.h;
  1213.     z80.l=sna.l;
  1214.  
  1215.     z80.fax=sna.fax;
  1216.     z80.aax=sna.aax;
  1217.     z80.bax=sna.bax;
  1218.     z80.cax=sna.cax;
  1219.     z80.dax=sna.dax;
  1220.     z80.eax=sna.eax;
  1221.     z80.hax=sna.hax;
  1222.     z80.lax=sna.lax;
  1223.  
  1224.     z80.ixh=sna.ixh;
  1225.     z80.ixl=sna.ixl;
  1226.     z80.iyh=sna.iyh;
  1227.     z80.iyl=sna.iyl;
  1228.  
  1229.     z80.i=sna.i;
  1230.     z80.r=sna.r | 0x080; /* bit 7 is stored somewhere else, always set */
  1231.     z80.im=sna.im & 0x03;
  1232.     z80.im=z80.im + 0x60; /* fixed normal video/kempston joystick */
  1233.  
  1234.     z80.sph=sp/256;
  1235.     z80.spl=sp%256;
  1236.     
  1237.     z80.pch=pc/256;
  1238.     z80.pcl=pc%256;
  1239.  
  1240.     /* all kinds of stuff put in "data" */
  1241.     z80.data=(sna.border & 0x07)*2; 
  1242.     if((sna.r & 0x80)!=0) z80.data=z80.data+1; /* here is bit 7 of r */
  1243.  
  1244.     /* image is not compressed, compression will be done by the */
  1245.     /* z80_write function.                                      */
  1246.     z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  1247.  
  1248.     if((sna.iff2 & 0x04) != 0) {
  1249.         z80.iff1=0xff;
  1250.         z80.iff2=0xff;
  1251.     } else {
  1252.         z80.iff1=0;
  1253.         z80.iff2=0;
  1254.     }
  1255. }
  1256.  
  1257. void SNPR_sna_to_prg(char * n)
  1258. {
  1259.     unsigned int addr;
  1260.     unsigned int sp;
  1261.     int i;
  1262.     unsigned char * p;
  1263.  
  1264.     /* clean header structure first */
  1265.     p=(unsigned char *) &prg;
  1266.     for(i=0; i < 256; i++)
  1267.         p[i]='\0';
  1268.  
  1269.     prg.c_0x61=0x61; /* size of image in sectors */
  1270.     prg.c_0x35=0x35; /* don't know yet */
  1271.     prg.c_0x03=0x03; /* don't know yet */
  1272.  
  1273.     sp=256*sna.sph+sna.spl;
  1274.     addr=sp-0x4000;
  1275.  
  1276.     /* these are on the stack */
  1277.     image[addr-1]=sna.a;
  1278.     image[addr-2]=sna.f;
  1279.     image[addr-3]=sna.r;
  1280.     image[addr-4]=sna.iff2;
  1281.  
  1282.     sp=sp-4;
  1283.  
  1284.     prg.name[0]='\0';
  1285.     strncpy(prg.name,n,10);
  1286.     prg.name[10]='\0';
  1287.  
  1288.     prg.b=sna.b;
  1289.     prg.c=sna.c;
  1290.     prg.d=sna.d;
  1291.     prg.e=sna.e;
  1292.     prg.h=sna.h;
  1293.     prg.l=sna.l;
  1294.  
  1295.     prg.fax=sna.fax;
  1296.     prg.aax=sna.aax;
  1297.     prg.bax=sna.bax;
  1298.     prg.cax=sna.cax;
  1299.     prg.dax=sna.dax;
  1300.     prg.eax=sna.eax;
  1301.     prg.hax=sna.hax;
  1302.     prg.lax=sna.lax;
  1303.  
  1304.     prg.ixh=sna.ixh;
  1305.     prg.ixl=sna.ixl;
  1306.     prg.iyh=sna.iyh;
  1307.     prg.iyl=sna.iyl;
  1308.  
  1309.     prg.i=sna.i;
  1310.     prg.iff2=sna.iff2;
  1311.  
  1312.     prg.sph=sp/256;
  1313.     prg.spl=sp%256;
  1314.     
  1315.     /* prg.border=sna.border; */
  1316. }
  1317.  
  1318. void SNAC_sna_to_ach()
  1319. {
  1320.     unsigned int addr;
  1321.     unsigned int sp;
  1322.     unsigned int pc;
  1323.     int i;
  1324.     unsigned char * p;
  1325.  
  1326.     /* clean header structure first */
  1327.     p=(unsigned char *) &ach;
  1328.     for(i=0; i < 256; i++)
  1329.         p[i]='\0';
  1330.  
  1331.     sp=256*sna.sph+sna.spl;
  1332.     addr=sp-0x4000;
  1333.     pc=image[addr]+256*image[addr+1];
  1334.     sp=sp+2;
  1335.  
  1336.     ach.f=sna.f;
  1337.     ach.a=sna.a;
  1338.     ach.b=sna.b;
  1339.     ach.c=sna.c;
  1340.     ach.d=sna.d;
  1341.     ach.e=sna.e;
  1342.     ach.h=sna.h;
  1343.     ach.l=sna.l;
  1344.  
  1345.     ach.fax=sna.fax;
  1346.     ach.aax=sna.aax;
  1347.     ach.bax=sna.bax;
  1348.     ach.cax=sna.cax;
  1349.     ach.dax=sna.dax;
  1350.     ach.eax=sna.eax;
  1351.     ach.hax=sna.hax;
  1352.     ach.lax=sna.lax;
  1353.  
  1354.     ach.ixh=sna.ixh;
  1355.     ach.ixl=sna.ixl;
  1356.     ach.iyh=sna.iyh;
  1357.     ach.iyl=sna.iyl;
  1358.  
  1359.     ach.i=sna.i;
  1360.     ach.r=sna.r;
  1361.  
  1362.     ach.border=sna.border;
  1363.  
  1364.     if((sna.iff2 & 0x04) != 0)
  1365.         ach.iff2=0xff;
  1366.     else
  1367.         ach.iff2=0x00;
  1368.  
  1369.     ach.im=sna.im;
  1370.  
  1371.     ach.sph=sp/256;
  1372.     ach.spl=sp%256;
  1373.     
  1374.     ach.pch=pc/256;
  1375.     ach.pcl=pc%256;
  1376. }
  1377.  
  1378. void SNKG_sna_to_kgb()
  1379. {
  1380.     unsigned int addr;
  1381.     unsigned int sp;
  1382.     unsigned int pc;
  1383.     int i;
  1384.     unsigned char * p;
  1385.  
  1386.     /* clean info structure first */
  1387.     p = (unsigned char *) &kgb;
  1388.     for(i=0; i < 202; i++)
  1389.         p[i]='\0';
  1390.  
  1391.     /* make some assumptions here */
  1392.     kgb.is3_1 = 3;        /* always 3, don't ask me why */
  1393.     kgb.colourmode = 1;    /* assume colour */
  1394.     kgb.soundmode = 1;    /* assume simple sound */
  1395.     kgb.haltmode = 1;    /* assume not in halt mode */
  1396.  
  1397.     sp=256*sna.sph+sna.spl;
  1398.     addr=sp-0x4000;
  1399.     pc=image[addr]+256*image[addr+1];
  1400.     sp=sp+2;
  1401.  
  1402.     kgb.f=sna.f;
  1403.     kgb.a=sna.a;
  1404.     kgb.b=sna.b;
  1405.     kgb.c=sna.c;
  1406.     kgb.d=sna.d;
  1407.     kgb.e=sna.e;
  1408.     kgb.h=sna.h;
  1409.     kgb.l=sna.l;
  1410.  
  1411.     kgb.fax=sna.fax;
  1412.     kgb.aax=sna.aax;
  1413.     kgb.bax=sna.bax;
  1414.     kgb.cax=sna.cax;
  1415.     kgb.dax=sna.dax;
  1416.     kgb.eax=sna.eax;
  1417.     kgb.hax=sna.hax;
  1418.     kgb.lax=sna.lax;
  1419.  
  1420.     kgb.ixh=sna.ixh;
  1421.     kgb.ixl=sna.ixl;
  1422.     kgb.iyh=sna.iyh;
  1423.     kgb.iyl=sna.iyl;
  1424.  
  1425.     kgb.i=sna.i;
  1426.  
  1427.     kgb.r=sna.r;
  1428.  
  1429.     /* kgb.border=sna.border; NOT IN KGB IMAGE! */
  1430.  
  1431.     /* Interupt mode is stored in a word in the KGB format. */
  1432.     /* Use byte accesses to be CPU independent              */
  1433.  
  1434.     switch (sna.im & 0x03) {
  1435.     case 0:    kgb.i_mode_h = 0xff;
  1436.         kgb.i_mode_l = 0xff;
  1437.         break;
  1438.     case 2: kgb.i_mode_h = 0;
  1439.         kgb.i_mode_l = 1;
  1440.         break;
  1441.     default:kgb.i_mode_h = 0;
  1442.         kgb.i_mode_l = 0;
  1443.         break;
  1444.     }
  1445.  
  1446.     if((sna.iff2 & 0x04) != 0)
  1447.         kgb.interruptstatus=0x01;
  1448.     else
  1449.         kgb.interruptstatus=0x00;
  1450.  
  1451.     kgb.sph=sp/256;
  1452.     kgb.spl=sp%256;
  1453.     
  1454.     kgb.pch=pc/256;
  1455.     kgb.pcl=pc%256;
  1456. }
  1457.  
  1458. /* 16K PAGE READ FUNCTION FOR .Z80 FORMAT */
  1459.  
  1460. /*
  1461.  * Function returns:
  1462.  *      0: No more pages
  1463.  *    1: Page read
  1464.  */
  1465. int RDPG_z80_read_page(char * s, FILE * fd)
  1466. {
  1467.     struct    z80_page_s page_info;
  1468.     unsigned int    len;
  1469.     unsigned int    pos;
  1470.     long        f_len;
  1471.  
  1472.     if(fread(&page_info,z80_pg_size,1,fd)!=1)    {
  1473.         return 0;
  1474.     }
  1475.     len = (256 * page_info.blklen_h) + page_info.blklen_l;
  1476.  
  1477.     switch(page_info.page_num) {
  1478.     case 0:    werr(FALSE,"%s - memory page 0 - 48K rom ignored",s);
  1479.         pos=0x0ffff;
  1480.         break;
  1481.     case 1:    werr(FALSE,"%s - memory page 1 - Interface 1 rom ignored",s);
  1482.         pos=0x0ffff;
  1483.         break;
  1484.     case 2:    werr(FALSE,"%s - memory page 2 - basic samram rom ignored",s);
  1485.         pos=0x0ffff;
  1486.         break;
  1487.     case 3:    werr(FALSE,"%s - memory page 3 - monitor samram rom ignored",s);
  1488.         pos=0x0ffff;
  1489.         break;
  1490.     case 4:    pos=0x04000;    /* second 16K of RAM area */
  1491.         break;
  1492.     case 5:    pos=0x08000;    /* third 16K of RAM area */
  1493.         break;
  1494.     case 6:    werr(FALSE,"%s - memory page 6 - shadow rom 8000-BFFF ignored",s);
  1495.         pos=0x0ffff;
  1496.         break;
  1497.     case 7:    werr(FALSE,"%s - memory page 7 - shadow rom C000-FFFF ignored",s);
  1498.         pos=0x0ffff;
  1499.         break;
  1500.     case 8:    pos=0;        /* first 16K of RAM area */
  1501.         break;
  1502.     case 9:    werr(FALSE,"%s - memory page 8 - 128K page 6 ignored",s);
  1503.         pos=0x0ffff;
  1504.         break;
  1505.     case 10:werr(FALSE,"%s - memory page 10 - 128K page7 ignored",s);
  1506.         pos=0x0ffff;
  1507.         break;
  1508.     default:werr(FALSE,"%s - memory page %d - Invalid page number -fatal-",s,page_info.page_num);
  1509.         exit(EXIT_FILE_ERROR);
  1510.         break;
  1511.     }
  1512.  
  1513.     if(pos == (unsigned int) 0x0ffff) {
  1514.         /* wrong page, seek over this page */
  1515.         if(fseek(fd, (long) len, SEEK_CUR)!=0)
  1516.             RERR_read_error(s, fd);
  1517.     } else {
  1518.         /* Valid 48K page, read and decompress */
  1519.  
  1520.         f_len = 0 - ftell(fd);
  1521.         Z80D_z80_decompress(fd, pos, 16384);
  1522.         f_len = f_len + ftell(fd);
  1523.  
  1524.         if((long) len != f_len) {
  1525.             werr(FALSE,"Z80 image corrupted, can't convert");
  1526.             fclose(fd);
  1527.             exit(EXIT_FILE_ERROR);
  1528.         }
  1529.     }
  1530.     return 1;
  1531. }
  1532.  
  1533. /* COMPRESSION/DECOMPRESSION for .Z80 FORMAT */
  1534.  
  1535. void Z80D_z80_decompress(FILE * fd, unsigned int start, unsigned int imsize)
  1536. {
  1537.     int          c,j,k;
  1538.     unsigned char l;
  1539.     unsigned char im;
  1540.  
  1541.     j=start;
  1542.     while(j<(start+imsize)) {
  1543.         c=getc(fd);
  1544.         if(c == -1) return;
  1545.         im = (unsigned char) c;
  1546.  
  1547.         if(im!=0xed) {
  1548.             image[j++]=im;
  1549.         } else {
  1550.             c=getc(fd);
  1551.             if(c == -1) return;
  1552.             im = (unsigned char) c;
  1553.             if(im!=0xed) {
  1554.                 image[j++]=0xed;
  1555.                 ungetc(im,fd);
  1556.             } else {
  1557.                 /* fetch count */
  1558.                 k=getc(fd);
  1559.                 if(k == -1) return;
  1560.                 /* fetch character */
  1561.                 c=getc(fd);
  1562.                 if(c == -1) return;
  1563.                 l = (unsigned char) c;
  1564.                 while(k!=0) {
  1565.                     image[j++]=l;
  1566.                     k--;
  1567.                 }
  1568.             }
  1569.         }
  1570.     }
  1571.  
  1572.     if(j!=(start+imsize)) {
  1573.         werr(FALSE,"Z80 image corrupted, can't decompress");
  1574.         exit(EXIT_FILE_ERROR);
  1575.     }
  1576. }
  1577.  
  1578. int Z80C_z80_compress()
  1579. {
  1580. #ifdef __TURBOC__
  1581.     unsigned char far * comp;
  1582. #else
  1583.     unsigned char * comp;
  1584. #endif
  1585.     unsigned int i,j;
  1586.     unsigned int num;
  1587.     unsigned char c,n;
  1588.     unsigned int ed;
  1589.  
  1590.     z80_size=(unsigned int) IMSIZE;
  1591.  
  1592.     /*
  1593.      * We need an intermediate buffer here, if the compressed image
  1594.      * is bigger than the uncompressed image than the image will
  1595.      * not be compressed to save space (!)
  1596.      */
  1597.  
  1598. #ifdef __TURBOC__
  1599.     comp=(unsigned char far *) farmalloc((unsigned long)(IMSIZE+0x0100));
  1600. #else
  1601.     comp=(unsigned char *) malloc((size_t)(IMSIZE+0x0100));
  1602. #endif
  1603.     if(comp==NULL) {
  1604.         werr(FALSE,"Warning: Not enough memory to compress the image, using uncopressed image");
  1605.         return NOTCOMPRESSED;
  1606.     }
  1607.  
  1608.     i=0;
  1609.     j=0;
  1610.     /* ensure 'ed' is not set */
  1611.     ed=NO;
  1612.     while(i<IMSIZE)    {
  1613.         c=image[i];
  1614.         i++;
  1615.         if(i<IMSIZE) {
  1616.             n=image[i];
  1617.         } else {
  1618.             /* force 'n' to be unequal to 'c' */
  1619.             n=c;
  1620.             n++;
  1621.         }
  1622.  
  1623.         if(c!=n) {
  1624.             comp[j]=c;
  1625.             j++;
  1626.             if(c==0xed) 
  1627.                 ed=YES;
  1628.             else
  1629.                 ed=NO;
  1630.         } else {
  1631.             if(c==0xed) {
  1632.                 /* two times 0xed - special care */
  1633.                 comp[j]=0xed;
  1634.                 j++;
  1635.                 comp[j]=0xed;
  1636.                 j++;
  1637.                 comp[j]=0x02;
  1638.                 j++;
  1639.                 comp[j]=0xed;
  1640.                 j++;
  1641.                 i++; /* skip second ED */
  1642.  
  1643.                 /* because 0xed is valid compressed we don't
  1644.                    have to watch it! */
  1645.                 ed=NO;
  1646.             } else if(ed==YES) {
  1647.                 /* can't compress now, skip this double pair */
  1648.                 comp[j]=c;
  1649.                 j++;
  1650.                 ed=NO;    /* 'c' can't be 0xed */
  1651.             } else {
  1652.                 num=1;
  1653.                 while(i<IMSIZE) {
  1654.                     if(c!=image[i])
  1655.                         break;
  1656.                     num++;
  1657.                     i++;
  1658.                     if(num==255)
  1659.                         break;
  1660.                 }
  1661.                 if(num <= 4) {
  1662.                     /* no use to compress */
  1663.                     while(num!=0) {
  1664.                         comp[j]=c;
  1665.                         j++;
  1666.                         num--;
  1667.                     }
  1668.                 } else {
  1669.                     comp[j]=0xed;
  1670.                     j++;
  1671.                     comp[j]=0xed;
  1672.                     j++;
  1673.                     comp[j]=(unsigned char) num;
  1674.                     j++;
  1675.                     comp[j]=c;
  1676.                     j++;
  1677.                 }
  1678.             }
  1679.         }
  1680.  
  1681.         if(j >= (IMSIZE-4)) {
  1682.             /* compressed image bigger or same than original */
  1683. #ifdef __TURBOC__
  1684.             farfree((void far *) comp);
  1685. #else
  1686.             free((void *) comp);
  1687. #endif
  1688.             return NOTCOMPRESSED;
  1689.         }
  1690.     }
  1691.     /* append "end of compressed area" mark */
  1692.     comp[j]=0;
  1693.     j++;
  1694.     comp[j]=0xed;
  1695.     j++;
  1696.     comp[j]=0xed;
  1697.     j++;
  1698.     comp[j]=0;
  1699.     j++;
  1700.  
  1701.     z80_size = j;
  1702.     
  1703.     /* copy back */
  1704.     i=0;
  1705.     j=0;
  1706.     while(i<IMSIZE)
  1707.         image[i++]=comp[j++];
  1708. #ifdef __TURBOC__
  1709.     farfree((void far *) comp);
  1710. #else
  1711.     free((void *) comp);
  1712. #endif
  1713.     return COMPRESSED;
  1714. }
  1715.